package com.zhny.aiot.leakage.valve.pressusre4.v2.plugin.model;

import com.google.common.collect.ImmutableMap;
import com.zhny.aiot.plugin.ICenterFacilities;
import com.zhny.aiot.plugin.IDeviceFactory;
import com.zhny.aiot.plugin.core.utils.MessageUtils;
import com.zhny.aiot.plugin.model.DeviceEntity;
import com.zhny.aiot.plugin.model.MessageEntry;
import com.zhny.aiot.plugin.model.MessageType;
import com.zhny.aiot.plugin.model.TaskEntity;
import com.zhny.aiot.plugin.v2.gateway.model.NodeV2RequestMessage;
import com.zhny.aiot.plugin.zhnygateway.GatewayEngine;
import com.zhny.aiot.plugin.zhnygateway.device.ZhnyConfig;
import com.zhny.aiot.plugin.zhnygateway.device.ZhnyDevice;
import com.zhny.aiot.plugin.zhnygateway.model.GatewayResponseMessage;
import com.zhny.aiot.plugin.zhnygateway.model.NodeRequestMessage;
import io.netty.buffer.ByteBufUtil;
import org.pf4j.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class Leakage4PressureV2Device extends ZhnyDevice<LeakageValve4PressureV2StoreEntry> {
    private static final Logger logger=LoggerFactory.getLogger (Leakage4PressureV2Device.class);
    private final Map<String, Integer> CommandOperations;

    public Leakage4PressureV2Device(GatewayEngine engine, IDeviceFactory<ZhnyConfig> factory, ICenterFacilities centerFacilities, DeviceEntity entity) {
        super (engine, factory, centerFacilities, entity);
        CommandOperations=new ImmutableMap.Builder<String, Integer> ()
                .put ("openValve1", 0x32)
                .put ("closeValve1", 0x31)
                .put ("openValve2", 0x34)
                .put ("closeValve2", 0x33)
                .put ("openValve3", 0x36)
                .put ("closeValve3", 0x35)
                .put ("openValve4", 0x38)
                .put ("closeValve4", 0x37)
                .put ("queryStatus", 0x39)
                .put ("queryPressure", 0x3b)
                .put ("queryVoltage", 0x3A).build ();
    }

    @Override
    public void onDecoder(GatewayResponseMessage message) {
        logger.info (message.toString ());
        int type=message.getDeviceType ();
        if(type == 0x01) {

            onMessage (message);
        }
        message.getDeviceData ().release ();
    }

    private void onMessage(GatewayResponseMessage message) {
        logger.info ("---start decoder leakage v2 message---");
        logger.info ("---decoder leakage v2 data[{}]---", ByteBufUtil.hexDump (message.getDeviceData ()));
        MessageEntry resultMsg=MessageUtils.createMessageEntry (this.getId ());
        resultMsg.setType (MessageType.RESULT);
        LeakageValve4PressureV2StoreEntry storeEntry=new LeakageValve4PressureV2StoreEntry ();
        int operation=message.getDeviceOper ();
        if(operation>=0x31 && operation<=0x38) {
            if(message.getDataLength () == 7) {
                resultMsg.setType (MessageType.ERROR);
                resultMsg.setData ("水利机械阀加入任务失败");
                logger.error ("[deviceNo:{},controllerNo:{}] 水利机械阀加入任务[{}]失败"
                        , getConfig ().getAddress (), getConfig ().getChannelNo (), operation);
                nofity (resultMsg);
                return;
            }else if(operation == 0x31) {
                storeEntry.setA(false);
                resultMsg.setData (storeEntry);
            }else if(operation == 0x32) {
                storeEntry.setA (true);
                resultMsg.setData (storeEntry);
            }else if(operation == 0x33) {
                storeEntry.setB (false);
                resultMsg.setData (storeEntry);
            }else if(operation == 0x34) {
                storeEntry.setB (true);
                resultMsg.setData (storeEntry);
            }else if(operation == 0x35) {
                storeEntry.setC (false);
                resultMsg.setData (storeEntry);
            }else if(operation == 0x36) {
                storeEntry.setC (true);
                resultMsg.setData (storeEntry);
            }else if(operation == 0x37) {
                storeEntry.setD (false);
                resultMsg.setData (storeEntry);
            }else if(operation == 0x38) {
                storeEntry.setD (true);
                resultMsg.setData (storeEntry);
            }
        }else if(operation == 0x39) {
            Boolean valve1Status=message.getDeviceData ().readUnsignedByte () == 1 ? true : false;
//            storeEntry.setAStatus (valve1Status);
            storeEntry.setAWaterFlow (valve1Status);
            Boolean valve2Status=message.getDeviceData ().readUnsignedByte () == 1 ? true : false;
//            storeEntry.setBStatus (valve2Status);
            storeEntry.setBWaterFlow (valve2Status);
            Boolean valve3Status=message.getDeviceData ().readUnsignedByte () == 1 ? true : false;
//            storeEntry.setCStatus (valve3Status);
            storeEntry.setCWaterFlow (valve3Status);
            Boolean valve4Status=message.getDeviceData ().readUnsignedByte () == 1 ? true : false;
//            storeEntry.setDStatus (valve4Status);
            storeEntry.setDWaterFlow (valve4Status);

            resultMsg.setData (storeEntry);
        }else if(operation == 0x3A) {
            storeEntry=new LeakageValve4PressureV2StoreEntry ();
            storeEntry.setVoltage (createVol (message.getDeviceData ().readShort ()));
            resultMsg.setData (storeEntry);
        }else if(operation == 0x3B) {
            String pressureA;
            String pressureB;
            String pressureC;
            String pressureD;

            pressureA=createPressure1 (message.getDeviceData ().readUnsignedShort ());
            pressureB=createPressure1 (message.getDeviceData ().readUnsignedShort ());
            pressureC=createPressure1 (message.getDeviceData ().readUnsignedShort ());
            pressureD=createPressure1 (message.getDeviceData ().readUnsignedShort ());

            storeEntry.setAPressure (pressureA);
            storeEntry.setBPressure (pressureB);
            storeEntry.setCPressure (pressureC);
            storeEntry.setDPressure (pressureD);
            storeEntry.setVoltage (createVol (message.getDeviceData ().readShort ()));
            resultMsg.setData (storeEntry);
        }
        logger.info ("leakage valve{} store[{}]", this.getDeviceEntity ().getName (), storeEntry);
        save (storeEntry);
        saveReal (storeEntry);
        nofity (resultMsg);
    }

    private String createPressure(int pressure) {
        double result=pressure / 100.00;
        if(result>=0.01) {
            Random random=new Random ();
            double randomDouble=random.nextInt (5) / 1000D;
            result=result+randomDouble;
        }else {
            result=0.000D;
        }
        return String.format ("%.3f", result);
    }

    private String createPressure1(int pressure) {
        double result=pressure / 1000.00;
        return String.format ("%.3f", result);
    }

    private double createVol(short vol) {
        return vol / 100.0;
    }

    private NodeRequestMessage encode(long key, Map<String, Object> commandMap) {
        for (String id : commandMap.keySet ()){
            if(CommandOperations.containsKey (id)) {
                Integer oper=CommandOperations.get (id);
                int length=4;
                return new NodeV2RequestMessage (getzhnyType ()+128, length, oper, Integer.parseInt (getConfig ().getAddress ()), key, null);
            }
        }
        return null;
    }

    @Override
    protected NodeRequestMessage onCommand(TaskEntity taskEntity) {
        if(StringUtils.isNullOrEmpty (taskEntity.getMethodName ()))
            return null;


        Map<String, Object> command=new HashMap<String, Object> ();
        command.put (taskEntity.getMethodName (), null);
        logger.info ("config address[{}]", Integer.parseInt (getConfig ().getAddress ()));
        return encode (taskEntity.getKey (), command);
    }

    @Override
    protected int getzhnyType() {
        return 0x01;
    }

    @Override
    protected void disposable() {

    }
}
